package srzy.driver

import srzy.socket._
import srzy.common.Common
import java.util.Formatter
import srzy.common.Logging
import scala.actors.Actor
import scala.actors.Actor._

object DCCMsgDealer extends Actor with Logging {

  var oc: scala.actors.OutputChannel[Any] = null
  val clq = new java.util.concurrent.LinkedBlockingQueue[String](500)

  override def act = {
    loop {
      react {
        case 'getRece => {
          if (clq.peek() == null) {
            oc = sender
          } else {
            sender ! clq.poll()
          }
        }
        case ('rece, receMsg: String) => {
          if (oc != null) {
            oc ! receMsg
            oc = null
          } else {
            clq.offer(receMsg)
          }
        }

        case a: Any =>
          logger.error("unknown pattern " + a.toString)
      }
    }
  }

}
object DCCServer {

  val a1 = Actor.actor {
    loop {
      react {
        case 'exit => exit()
        case 'get => {
          sender ! dccssc.accept
        }
      }
    }
  }

  val dccServer = new DCCServer(a1)
  dccServer.start
  def apply() = dccServer

  val dccssc = new DCCSocketServerConn {
    val serverSocket = SocketServerConn.create(17953)
  }

}

class DCCServer(a1: Actor) extends Actor with Logging {

  def getSocketConn = new DCCSocketConn {
    val socket = (a1 !! 'get).apply.asInstanceOf[java.net.Socket]
    val outStream = socket.getOutputStream()
    val inStream = socket.getInputStream()
  }

  override def act = {

    import srzy.diameter._
    var l: srzy.socket.DCCSocketConn = getSocketConn
    val pp = new xml.PrettyPrinter(800, 2)
    var i: Int = 1
    var scenario: scala.xml.Node = null
    var init: scala.xml.Elem = null
    var traffics: scala.xml.NodeSeq = scala.xml.NodeSeq.Empty
    var txt: String = ""
    //    var fileName = ""

    while (true) {
      //      fileName = getFileName
      try {
        val arr = l.read
        val node = arr.toDCCNode
        val m = pp.format(arr.toDCCNode)
        //        println(m)
        node.attributes.apply("name").head.text match {
          case "DWR" => {
            l.write(srzy.socket.DCCSocketConn.DWAMsg.toBytes)
          }
          case "CER" => {
            init = {
              <init>
                <send channel="channel-1">{ node }</send>
                <receive channel="channel-1"><command name="CEA"></command></receive>
              </init>
            }
            l.write(srzy.socket.DCCSocketConn.CEANullMsg.toBytes)
          }
          case "CCR" => {
            val sid = (node \\ "avp").iterator.toList
              .filter(_.attribute("name").getOrElse("").toString() == "Session-Id")
              .headOption match {
                case Some(v) => v.attribute("value").getOrElse("").toString()
                case None => ""
              }
            val cca = (<command name="CCA"><avp name="Session-Id" value={ sid }></avp></command>).toBytes
            traffics = traffics ++
              <send channel="channel-1">{ node }</send> ++
              <receive channel="channel-1"><command name="CCA"></command></receive>
            l.write(cca)
          }
          case _ =>
        }
      } catch {
        case sce: SocketClosedException => {
          l.close
          scenario = <scenario>
                       { if (init != null) init else "" }
                       <traffic> { traffics }</traffic>
                     </scenario>
          //          println(scenario)
          println("socket closed normally ,reconnect start")

          val llll = new xml.PrettyPrinter(800, 2)
          txt = """<?xml version="1.0" encoding="iso-8859-1"?>""" + "\n" + llll.format(scenario)

          DCCMsgDealer ! ('rece, txt)
          txt = ""
          traffics = scala.xml.NodeSeq.Empty
          l = getSocketConn
        }
        case ex: Exception => {
          l.close
          //          ex.printStackTrace()
          logger.debug("socket error ,reconnect start")
          l = getSocketConn
        }
      }

    }
  }

}